import { mat4, vec3, quat } from '../gl-matrix/index.js'

export class BoxCollider2D {
    constructor(options) {
        this.isTrigger = !!options.isTrigger;
        this.isRigid = !!options.isRigid;
        this.colliders = [];

        //本地包围盒
        this.min = options.min;
        this.max = options.max;

        //世界包围盒
        this._worldMin = vec3.create();
        this._worldMax = vec3.create();
        this._worldMatrix = mat4.create();
        this._tmpPoint = vec3.create();
    }

    setWorldBox(martix) {
        if (mat4.exactEquals(this._worldMatrix, martix)) return;

        mat4.copy(this._worldMatrix, martix);

        //左下角那个点
        vec3.transformMat4(this._worldMin, this.min, martix);

        //右上角那个点
        vec3.transformMat4(this._worldMax, this.max, martix);

        //右下角那个点
        vec3.set(this._tmpPoint, this.max[0], this.min[1], 0);
        vec3.transformMat4(this._tmpPoint, this._tmpPoint, martix);

        this._setMin(this._worldMin, this._tmpPoint);
        this._setMax(this._worldMax, this._tmpPoint);

        //左上角那个点
        vec3.set(this._tmpPoint, this.min[0], this.max[1], 0);
        vec3.transformMat4(this._tmpPoint, this._tmpPoint, martix);

        this._setMin(this._worldMin, this._tmpPoint);
        this._setMax(this._worldMax, this._tmpPoint);
    }

    isTouching(other) {
        let noTouch = other._worldMin[0] >= this._worldMax[0]
            || other._worldMax[0] <= this._worldMin[0]
            || other._worldMin[1] >= this._worldMax[1]
            || other._worldMax[1] <= this._worldMin[1];

        return !noTouch;
    }

    calculateBack(other) {
        if (this.isTouching(other)) {
            let x = 0;
            let y = 0;
            let z = 0;

            let left = this._worldMin[0] - other._worldMax[0];
            let right = this._worldMax[0] - other._worldMin[0];

            let bottom = this._worldMin[1] - other._worldMax[1];
            let up = this._worldMax[1] - other._worldMin[1];

            let arr = [Math.abs(left), Math.abs(right), Math.abs(bottom), Math.abs(up)];

            let index = this._getMinIndex(arr);

            switch (index) {
                case 0:
                    x = left;
                    y = 0;
                    break;

                case 1:
                    x = right;
                    y = 0;
                    break;

                case 2:
                    x = 0;
                    y = bottom;
                    break;

                case 3:
                    x = 0;
                    y = up;
                    break;
            }

            vec3.set(this._tmpPoint, x, y, z);

            return this._tmpPoint;
        }
        else {
            return null;
        }
    }

    _setMin(out, other) {
        if (other[0] < out[0]) {
            out[0] = other[0];
        }

        if (other[1] < out[1]) {
            out[1] = other[1];
        }
    }

    _setMax(out, other) {
        if (other[0] > out[0]) {
            out[0] = other[0];
        }

        if (other[1] > out[1]) {
            out[1] = other[1];
        }
    }

    _getMinIndex(arr) {
        let result = 0;
        let temp = null;

        for (let i = 0; i < arr.length; i++) {
            let item = arr[i];

            if (temp == null) {
                temp = item;
            }
            else if (item < temp) {
                temp = item;
                result = i;
            }
        }

        return result;
    }
}